package com.happy3w.ssp.schoolmatehome.component.wx;

import com.happy3w.ssp.schoolmatehome.exception.MessageException;
import com.happy3w.ssp.schoolmatehome.utils.JsonUtil;
import com.happy3w.toolkits.message.MessageRecorderException;
import lombok.Data;
import lombok.Getter;
import lombok.Setter;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Component;
import org.springframework.web.client.RestTemplate;
import org.springframework.web.util.UriComponentsBuilder;

@Slf4j
@Component
public class WeChatService {

    private final WxConfig config;
    private final RestTemplate restTemplate;

    public WeChatService(WxConfig wxConfig, RestTemplate restTemplate) {
        this.config = wxConfig;
        this.restTemplate = restTemplate;
    }

    private static final String WEB_LOGIN_API_URL = "https://api.weixin.qq.com/sns/oauth2/access_token";
    public WeChatSession getWebSession(String code) {
        // 构建请求 URL
        String url = UriComponentsBuilder.fromUriString(WEB_LOGIN_API_URL)
                .queryParam("appid", config.getWeb().getAppId())
                .queryParam("secret", config.getWeb().getAppSecret())
                .queryParam("code", code)
                .queryParam("grant_type", "authorization_code")
                .toUriString();

        // 发送请求并解析响应
        String jsonResponse = restTemplate.getForObject(url, String.class);
        WebSessionResponse response = JsonUtil.fromJson(jsonResponse, WebSessionResponse.class);

        if (response != null && response.getUnionid() != null) {
            WeChatSession session = new WeChatSession();
            session.setUnionid(response.getUnionid());
            session.setOpenid(response.getOpenid());
//            session.setSessionKey(response.access_token());
            session.setAccessToken(response.getAccess_token());
            return session;
        } else {
            throw new MessageException("Failed to get WeChat session");
        }
    }

    @Data
    private static class WebSessionResponse {
        private String access_token;
        private String refresh_token;
        private String unionid;
        private String openid;
        private String scope;
        private int expires_in;
    }

    private static final String MINI_LOGIN_API_URL = "https://api.weixin.qq.com/sns/jscode2session"; // 微信小程序使用
    public WeChatSession getMiniSession(String code) {
        // 构建请求 URL
        String url = UriComponentsBuilder.fromUriString(MINI_LOGIN_API_URL)
                .queryParam("appid", config.getMini().getAppId())
                .queryParam("secret", config.getMini().getAppSecret())
                .queryParam("js_code", code)
                .queryParam("grant_type", "authorization_code")
                .toUriString();

        // 发送请求并解析响应
        String jsonResponse = restTemplate.getForObject(url, String.class);
        MiniSessionResponse response = JsonUtil.fromJson(jsonResponse, MiniSessionResponse.class);

        if (response != null && response.getUnionid() != null) {
            WeChatSession session = new WeChatSession();
            session.setUnionid(response.getUnionid());
            session.setOpenid(response.getOpenid());
            session.setSessionKey(response.getSession_key());
            return session;
        } else {
            throw new MessageException("Failed to get WeChat session");
        }
    }
    @Data
    private static class MiniSessionResponse {
        private String unionid;
        private String openid;
        private String session_key;
        private String errcode;
        private String errmsg;
    }


    public UserInfoResponse getUserInfo(WeChatSession session) {
        String url = String.format("https://api.weixin.qq.com/sns/userinfo?access_token=%s&openid=%s", session.getAccessToken(), session.getOpenid());
        String jsonResponse = restTemplate.getForObject(url, String.class);
         return JsonUtil.fromJson(jsonResponse, UserInfoResponse.class)
                .regular();
    }


    public MiniAccessTokenResponse getMiniAccessToken() {
        String url = UriComponentsBuilder.fromUriString("https://api.weixin.qq.com/cgi-bin/token")
                .queryParam("appid", config.getMini().getAppId())
                .queryParam("secret", config.getMini().getAppSecret())
                .queryParam("grant_type", "client_credential")
                .toUriString();

        String jsonResponse = restTemplate.getForObject(url, String.class);
        return JsonUtil.fromJson(jsonResponse, MiniAccessTokenResponse.class);
    }

    @Getter
    @Setter
    public static class MiniAccessTokenResponse {
        private String access_token;
        private String expires_in;
    }

    private HttpEntity<String> buildRequest(String body) {
        // Set headers
        HttpHeaders headers = new HttpHeaders();
        headers.add("Content-Type", "application/json");

        return new HttpEntity<>(body, headers);
    }

    public String generateScheme(String path, MiniAccessTokenResponse accessToken) {
        String url = UriComponentsBuilder.fromUriString("https://api.weixin.qq.com/wxa/generatescheme")
                .queryParam("access_token", accessToken.getAccess_token())
                .toUriString();

        GenerateSchemeRequest request = new GenerateSchemeRequest();
        request.jump_wxa.path = path;
        request.is_expire = false;
//        request.jump_wxa.query = "jumpCode=1234";
        HttpEntity<String> requestEntity = buildRequest(JsonUtil.toJson(request));
        ResponseEntity<String> response = restTemplate.exchange(url, HttpMethod.POST, requestEntity, String.class);

        if (!response.getStatusCode().is2xxSuccessful()) {
            throw new MessageRecorderException("Failed to create scheme: " + path);
        }
        log.info(response.getBody());
        GenerateSchemeResponse typeResponse = JsonUtil.fromJson(response.getBody(), GenerateSchemeResponse.class);
        return typeResponse.openlink;
    }

    @Getter
    @Setter
    private static class GenerateSchemeRequest {
        private JumpWxa jump_wxa = new JumpWxa();
        private Boolean is_expire;
    }

    @Getter
    @Setter
    private static class GenerateSchemeResponse {
        private String openlink;
    }

    @Getter
    @Setter
    private static class JumpWxa {
        private String path;
    }
}
